package com.woniuxy.movice.service.imp;

import java.math.BigDecimal;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.List;
import java.util.Random;
import java.util.concurrent.TimeUnit;


import javax.annotation.Resource;



import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.woniuxy.movice.dto.OrderInfo;
import com.woniuxy.movice.dto.Page;
import com.woniuxy.movice.entity.Orders;
import com.woniuxy.movice.entity.Rounds;
import com.woniuxy.movice.entity.Users;
import com.woniuxy.movice.exception.OrderException;
import com.woniuxy.movice.exception.RoundException;
import com.woniuxy.movice.mapper.OrderMapper;
import com.woniuxy.movice.mapper.OrderStateMapper;
import com.woniuxy.movice.mapper.OrdersMapper;
import com.woniuxy.movice.mapper.RoundMapper;
import com.woniuxy.movice.mq.Producer;
import com.woniuxy.movice.pojo.Order;
import com.woniuxy.movice.service.OrderService;
import com.woniuxy.movice.service.RoundService;
import com.woniuxy.movice.util.ConvertUtil;
import com.woniuxy.movice.util.EmptyUtil;

@Service
public class OrderServiceImp implements OrderService {

	@Autowired
	private RedisTemplate<Object, Object> redisTemplate;
	@Autowired
	private OrdersMapper ordersMapper;
	@Autowired
	private RoundService roundService;
	@Autowired
	private Producer producer;
	@Autowired
	private RoundMapper rounMapper;

	@Resource
	private OrderMapper orderMapper;
	@Resource 
	private OrderStateMapper orderStateMapper;
	

	@Override
	@Transactional
	public Orders creatOrder(Integer roundId, String selectSets, Users user) {
		// Users user=new Users(1, "12345678910", "1234", new Vip(1, "asda",0.9
		// ), new BigDecimal("0"), 1, 0);
		// 用户状态为超级管理员
		if (user.getUstate() == 1) {
			throw new OrderException("超级管理员无法购票");
		}
		// 获取该场次信息
		try {
			// 查询场次座位信息
			Rounds round = roundService.getSetsInfo(roundId);
			// 将查询出来的座位信息和前端选择的座位信息都转为二维数组，遍历用户选择的座位是否可选
			Integer[][] seats = ConvertUtil.convertStringTOArrays(round.getYtlayout());
			Integer[][] selectedSeats = ConvertUtil.convertStringTOArrays(selectSets);
			
			
			if (selectedSeats.length == 0) {
				throw new OrderException("没有选择座位");
			}
			// 判断选择的座位是否为可选的，如果可选则更新该座位为已选
			for (int i = 0; i < selectedSeats.length; i++) {
				if (seats[selectedSeats[i][0]][selectedSeats[i][1]] != 0) {
					throw new OrderException(selectedSeats[i][0] + "排" + selectedSeats[i][1] + "列：该座位不能选");
				}
				seats[selectedSeats[i][0]][selectedSeats[i][1]] = 2;
			}
			String updateSeats = ConvertUtil.convertObjectTOJSON(seats);
			round.setYtlayout(updateSeats);
			// 产生订单对象，插入数据库
			Orders order = creatOrder(round, user, selectSets);
			int resultRow = ordersMapper.insert(order);
			if (resultRow != 1) {
				throw new OrderException("创建订单失败");
			}
			// 更新数据库该场次座位信息
			roundService.updateLayout(roundId, updateSeats);
			// 放入mq,超时自动取消
			producer.sendOrder(order);
			// 更新redis中该场次的信息
			long destroyTime = round.getPend().getTime() - new Date().getTime();
			redisTemplate.opsForValue().set("Round" + round.getId(), round, destroyTime, TimeUnit.MILLISECONDS);
			return order;
		} catch (RoundException e) {
			throw new OrderException(e.getMessage());
		}
	}

	/**
	 * 
	 * 产生订单对象
	 * 
	 * @param round
	 * @param user
	 * @param selectSets
	 * @return
	 */
	private static Orders creatOrder(Rounds round, Users user, String selectSets) {
		Orders orders = new Orders();
		orders.setSelectedSets(selectSets);
		orders.setUid(user.getUid());
		orders.setOstate(1);
		orders.setMid(round.getMovie().getId());// 设置影片id
		orders.setCid(round.getId());// 设置场次id
		orders.setYid(round.getCinema().getYid());// 设置影院id
		DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
		String OderNum = LocalDateTime.now().format(dtf) + new Random().nextInt(10) + new Random().nextInt(10);
		orders.setOnum(OderNum);
		orders.setOtime(new Date(Instant.now().toEpochMilli()));
		// 折扣
		BigDecimal discount = new BigDecimal(user.getVip().getVdiscount());
		// 计算订单价格
		String num = ConvertUtil.convertStringTOArrays(selectSets).length + "";
		orders.setOprice(new BigDecimal(num).multiply(round.getPprice()).multiply(discount));
		return orders;
	}

	@Override
	public Page<Order> finAllOrder(Integer uid, Integer page, Integer size, Integer state) {
		Page<Order> pageDTO = new Page<Order>();
		pageDTO.setCount(size);
		pageDTO.setIndex(page - 1);
		List<Order> orders = ordersMapper.findAllOrder(uid, pageDTO, state);
		pageDTO.setMes(orders);
		return pageDTO;
	}

	@Override
	public Order findOrderByID(Integer id) throws OrderException {
		Order order = ordersMapper.findOrderByID(id);
		Rounds newround = rounMapper.findRoundById(order.getRound().getId());
		order.setRound(newround);
		if (EmptyUtil.isEmpty(order)) {
			throw new OrderException("订单不存在");
		}
		return order;
	}

	@Override
	public int updateOrderByOnum(Orders order) {
		return ordersMapper.updatePayState(order);
	}

	@Override
	public boolean takeTicket(String account, String orderId) {
		Order order = ordersMapper.findOrderByOnum(orderId);
		if (!order.getUser().getAccount().equals(account)) {
			throw new OrderException("手机号与订单号不匹配");
		}
		if (order.getOstate().equals(1)) {
			throw new OrderException("订单未支付");
		}
		if (!order.getOstate().equals(2)) {
			throw new OrderException("电影票已取");
		}
		ordersMapper.updateState(orderId, 3);
		return true;
	}

	@Override
	public void updateRefund(String onumber, int ostate) {
		int re=ordersMapper.updateOstate(onumber, ostate);
	}

	@Override
	public List<OrderInfo> showOrder(int uid) {
		return orderMapper.showOrder(uid);
	}

	@Override
	public String findOrderStateByOstate(Integer ostate) {
		return orderStateMapper.findOrderStateByOstate(ostate);
	}

	@Override
	public int delOrderByOid(int oid) {
		return orderMapper.delOrderByOid(oid);
	}

}
